package com.example.webrtcdemo.webrtc;


import com.example.webrtcdemo.utils.SigUtil;
import com.zhangke.websocket.SocketListener;
import com.zhangke.websocket.WebSocketHandler;
import com.zhangke.websocket.WebSocketManager;
import com.zhangke.websocket.WebSocketSetting;
import com.zhangke.websocket.dispatcher.DefaultResponseDispatcher;
import com.zhangke.websocket.response.ErrorResponse;
import com.zhangke.websocket.util.LogUtil;

import org.java_websocket.framing.Framedata;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @作者: smile
 * @时间: 2025/9/27 17:18
 * @描述:
 **/
public class WebSocketUtils {
    public String TAG = "WebSocketUtils";
    public volatile static WebSocketUtils instacne;
    public WebSocketManager mWebSocketManager;
    public String currentWebSocketUrl = "";
    public boolean isInit = false;
    public static WebSocketUtils getInstance() {
        if (instacne == null) {
            instacne = new WebSocketUtils();
            synchronized (WebSocketUtils.class){
                if(instacne == null){
                    instacne = new WebSocketUtils();
                }
            }
        }
        return instacne;
    }

    public void init(){
        initWebSocket();
    }

    private  void initWebSocket() {
        String userId = "10000";
        String platform = "android";
        String target = "app";
        String version = "10001";
        String sdkVer = "100";
        String baseUrl = "wss://iot-test.petgugu.com";
        String wsPath= "/ws";
        Map<String, String> params = new HashMap<>();
        params.put("platform", platform);
        params.put("user_id", userId);
        params.put("target", target);
        params.put("version", version);
        params.put("sdkver", sdkVer);

      //  currentWebSocketUrl = "ws://120.79.206.28:3590/ws?platform="+platform+"&user_id="+userId+"&target"+target+"&version"+version+"&sdkver="+sdkVer;
        currentWebSocketUrl = buildWebSocketUrl(baseUrl,wsPath,params);
        LogUtil.d(TAG, "当前连接的webSocket链接地址：" + currentWebSocketUrl);

        // 4. 准备签名参数（与URL参数保持一致，避免冗余）
        Map<String, List<String>> signatureParams = new HashMap<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            signatureParams.put(entry.getKey(), Collections.singletonList(entry.getValue()));
        }

        // 5. 生成签名
        String signature = SigUtil.INSTANCE.sigV1(userId, wsPath, signatureParams, null);
        LogUtil.e(TAG, "===加密后的参数为===" + signature);

        // 6. 配置WebSocket头部
        WebSocketSetting mWebSocketSetting = getWebSocketSetting(currentWebSocketUrl);
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", signature);
        mWebSocketSetting.setHttpHeaders(headerMap);

        // 7. 初始化并连接
        mWebSocketManager = WebSocketHandler.init(mWebSocketSetting);
        connectWebSocket();
    }

    private static WebSocketSetting getWebSocketSetting(String currentWebSocketUrl) {
        WebSocketSetting mWebSocketSetting = new WebSocketSetting();
        mWebSocketSetting.setConnectUrl(currentWebSocketUrl);
        //设置连接超时时间
        mWebSocketSetting.setConnectTimeout(10 * 1000);
        //设置心跳间隔时间
        mWebSocketSetting.setConnectionLostTimeout(20);
        //设置断开后的重连次数，可以设置的很大，不会有什么性能上的影响
        mWebSocketSetting.setReconnectFrequency(2);
        //设置消息分发器，接收到数据后先进入该类中处理，处理完再发送到下游
        mWebSocketSetting.setResponseProcessDispatcher(new DefaultResponseDispatcher());
        mWebSocketSetting.setProcessDataOnBackground(true);
        mWebSocketSetting.setReconnectWithNetworkChanged(true);
        return mWebSocketSetting;
    }

    public  void connectWebSocket(){
        try {
            if(mWebSocketManager==null){
                return;
            }
            mWebSocketManager.addListener(new SocketListener() {
                @Override
                public void onConnected() {
                    LogUtil.e(TAG ,"===连接成功====");
                }

                @Override
                public void onConnectFailed(Throwable throwable) {
                    LogUtil.e(TAG , "===连接失败====");
                }

                @Override
                public void onDisconnect() {
                    LogUtil.e(TAG , "===断开连接====");
                }

                @Override
                public void onSendDataError(ErrorResponse errorResponse) {
                    LogUtil.e(TAG , "===发送数据失败====" + errorResponse.getDescription());
                }

                @Override
                public <T> void onMessage(String msg, T t) {
                    LogUtil.e(TAG ,"===接收到消息msg===="+msg);
                }

                @Override
                public <T> void onMessage(ByteBuffer bytes, T t) {
                    LogUtil.e(TAG ,"===接收到消息byteBuffer====");
                    ByteBuffer rBuffer = ByteBuffer.allocate(1024);
                    Charset charset = StandardCharsets.UTF_8;
                    try {
                        String receiveText = charset.newDecoder().decode(rBuffer.asReadOnlyBuffer()).toString();
                        LogUtil.e(TAG ,"===接收到消息byteBuffer====" + receiveText);
                    } catch (CharacterCodingException e) {
                        throw new RuntimeException(e);
                    }
                }

                @Override
                public void onPing(Framedata pingData) {
                    LogUtil.e(TAG , "===心跳onPing===" + pingData);
                }

                @Override
                public void onPong(Framedata framedata) {
                    LogUtil.e(TAG , "===心跳onPong===" + framedata);
                }
            });
            mWebSocketManager.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 安全构建WebSocket URL，自动处理参数编码和格式
     * 避免特殊字符导致的URL错误
     */
    private String buildWebSocketUrl(String baseUrl, String path, Map<String, String> params) {
        // 处理基础URL和路径的拼接
        StringBuilder urlBuilder = new StringBuilder(baseUrl);
        if (path != null && !path.isEmpty() && !path.startsWith("/")) {
            urlBuilder.append("/");
        }
        urlBuilder.append(path);

        // 拼接查询参数（带URL编码）
        if (params != null && !params.isEmpty()) {
            urlBuilder.append("?");
            int index = 0;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                try {
                    // 对参数名和值进行编码，处理特殊字符
                    String encodedKey = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.name());
                    String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name());
                    urlBuilder.append(encodedKey).append("=").append(encodedValue);
                } catch (UnsupportedEncodingException e) {
                    // UTF-8编码是所有Java环境都支持的，此处异常理论上不会发生
                    throw new RuntimeException("URL编码失败", e);
                }
                // 不是最后一个参数则添加&
                if (index != params.size() - 1) {
                    urlBuilder.append("&");
                }
                index++;
            }
        }
        return urlBuilder.toString();
    }

}
